<?php

/**
* a webappkit tool to execute unit tests using a test database.
* sometimes you can't or don't want to use mock database connectors
* but don't want either to mess up your real data.
*
* this tool creates a fake database before issuing tests, and drop it after.
* insert the fake database definition into tool configuration file as this :
* [db]
* name = "fake database name"
* ; following data is optional, current connection will be used if existing
* host = ""
* user = ""
* pwd = ""
* [tables]
* ; name = "SQL creation command on a single line"
* mytable = "CREATE TABLE mytable(id primary key integer not null, value varchar(128))"
* [data]
* ; anykey = "row insertion command on a single line"
*/
class SimpleTestMysqlTool extends SimpleTestTool {

	public static function toolFactory($kit_id,$cfg=array()) {
		return new SimpleTestMysqlTool($kit_id,$cfg);
	}

	public static $default_cfg=array(
		'db'=>array(
			'name'=>'unit_tests'
			,'encoding'=>'utf8'
			,'create'=>true
			,'drop' => false
			,'host'=>'localhost'
			,'user'=>''
			,'pwd'=>'')
		,'tables'=>array() // table_name = creation query
		,'data'=>array() // n = data row creation query
	);

	protected $encoding;

	function _init() {
		$this->db_name=isset($this->cfg['db']['name'])?$this->cfg['db']['name']:'test';
	}

	/**
	 * connects to database server
	 * creates tests db if necessary
	 * creates tables and data
	 */
	function setUp() {
		// connecting
		if (!$this->_connect()) {
			return false;
		}
		$this->_populateDb();
		return true;
	}

	/**
	 * eventually drop tests database
	 */
	function tearDown() {
		// dropping test database
		if ($this->cfg['db']['drop']) {
			$sql = 'DROP DATABASE '.$this->db_name;
			if (!mysql_query($sql)) {
				trigger_error("could not drop database {$this->db_name} using query $sql",E_USER_WARNING);
			}
		}
	}

	/**
	 * connects to database
	 */
	function _connect() {
		$host=$this->cfg['db']['host'];
		$user=$this->cfg['db']['user'];
		$pwd=$this->cfg['db']['pwd'];
		if (!@mysql_connect($host,$user,$pwd)) {
			// throw new WakException("could not connect to host {$host}");
			//trigger_error("could not connect to host {$host}",E_USER_WARNING);
			return false;
		}
		// set connexion encoding
		if ($this->cfg['db']['encoding'])
			$this->_setEncoding($this->cfg['db']['encoding']);
		// creating test database
		if ($this->cfg['db']['create']) {
			$sql='CREATE DATABASE IF NOT EXISTS '.$this->db_name;
			if ($this->encoding)
				$sql.=' CHARACTER SET '.$this->encoding;
			if (!mysql_query($sql)) {
				trigger_error("could not create database {$this->db_name} using query $sql",E_USER_WARNING);
			}
		}
		// switching to new database
		if (!mysql_select_db($this->db_name)) {
			trigger_error("could not switch to test database {$this->db_name}",E_USER_ERROR);
			// DO NOT ISSUE TEST TO ANOTHER DB !!!
			exit;
			return false;
		}
		return true;
	}

	/**
	 * eventually create tables and data
	 * from the sql queries located in the config
	 * @access protected
	 * @return bool
	 */
	function _populateDb() {
		// building tables
		if (!is_array($this->cfg['tables'])) {
			return false;
		}
		foreach ($this->cfg['tables'] as $table => $create_sql) {
			// dropping table if exists
			mysql_query('DROP TABLE '.$table);
			// creating table
			if (!mysql_query($create_sql)) {
				trigger_error("could not create table {$table} , error was ".mysql_error(),E_USER_WARNING);
				echo '<pre>'.$create_sql.'</pre>';
			}
		}
		// dumping test data
		if (!is_array($this->cfg['data'])) {
			return false;
		}
		foreach ($this->cfg['data'] as $line => $sql) {
			if (!mysql_query($sql)) {
				trigger_error("could not insert row {$line} using query $sql",E_USER_WARNING);
				echo mysql_error();
			}
		}
		return true;
	}

	/**
	 * set encoding for connexion
	 * @param string encoding
	 */
	function _setEncoding($encoding) {
		// MySQL 4.1
		if (!$this->_query("SET NAMES '$encoding'")
		// MySQL 4.0
		and !$this->_query("SET CHARACTER SET '$encoding'")) {
			trigger_error("failed to set encoding $encoding : ".mysql_error());
			return false;
		}
		$this->encoding=$encoding;
		return true;
    }

	/**
	 * execute a query
	 */
	function _query($sql) {
		return mysql_query($sql);
	}
}
